package changceilingcolor003;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import sun.misc.Queue;
import toxi.geom.Vec3D;

public class World {

	ChangCeilingColor003 p5;
	ArrayList<Actors> m_AllAttraction = null;
	CheckPaths m_new = new CheckPaths();
	
	private final Lock attracotrsConnectionlock = new ReentrantLock();

	ArrayList<Actors> GetAttractionList()
	{
		return 	m_AllAttraction;
	}
	World(ChangCeilingColor003 _p5) {
		p5 = _p5;		
	}

	//setup 
	void init() {
		if(p5.Vistor){
		deployPerson(p5.pop*p5.Capacity_1/100, 1);
		}
		if(p5.Artist){
		deployPerson(p5.pop*p5.Capacity_2/100, 2);
		}
		if(p5.Collector){
		deployPerson(p5.pop*p5.Capacity_3/100, 3);
		}
	}
	//draw
	void run() {
		p5.PrevTemperatureGrid = p5.TemperatureGrid;
		
		for(int f = 0; f<p5.m_num_of_floor;++f)
		{
			for(int x  = 0; x < p5.width ;++x)
			{
				for(int y  = 0; y < p5.height ;++y)
				{					
					p5.TemperatureGrid[x][y][f] = 100;
				}			
			}
		}
		
		
		
		if(p5.activateAttractorsTemprature)
		{
			for (int i=0;i<p5.alisDst.size();i++) {
				Attraction attarction=(Attraction )p5.alisDst.get(i);
				attarction.UpdateTemperature();		
			}	
		}
		
		
		
		runPeople();
		
	}

	void runPeople() {
			
		p5.AllActiveActors.clear();
		p5.AllActiveActors.addAll(p5.alisDst);
		p5.AllActiveActors.addAll(p5.alisPeop);
		
		if(!p5.PausePeople)
		{

			///update the people state and deploy new one if needed
			for (int i=0;i<p5.alisPeop.size();i++) {
				Person p=(Person)p5.alisPeop.get(i); 			//
				if (p.there==true) {
					p5.alisPeop.remove(i);
					deployPerson(1, p.m_type);
				}
				else {
					p.update(this);   
				}
			}
		}
		
		
		
		
		if(p5.displayPossiblePath)
		{
		DrawPossiblePath();
		}
		
	}
	
	public void CheckPossiblePath()
	{
		for (int i=0;i<p5.alisDst.size();i++) {
			Attraction attarction=(Attraction )p5.alisDst.get(i);
			attarction.m_ConnectedAttractors.clear();		
		}			
		
		for (int i=0;i<p5.alisDst.size();i++) {
			Attraction attarction=(Attraction )p5.alisDst.get(i);
			attarction.update(this);		
		}

		m_new.CheckIfEntranceAndExitsConnected();			
	}
	
	public void DrawPossiblePath()
	{
		
		
		try {
			attracotrsConnectionlock.lock();
			p5.stroke(0, 255, 255);////////////////////////////////////show path
			//p5.strokeWeight(5);
			p5.strokeWeight(1);
			
			for(int i =0; i<m_new.m_allPossiblePaths.size();++i)
			{
				for(int j =1; j < m_new.m_allPossiblePaths.get(i).size();++j)
				{
					Attraction FromAttraction = m_new.m_allPossiblePaths.get(i).get(j-1);
					Attraction ToAttraction = m_new.m_allPossiblePaths.get(i).get(j);
					p5.line(FromAttraction.GetLocation().x, FromAttraction.GetLocation().y, FromAttraction.GetLocation().z, 
							ToAttraction.GetLocation().x, ToAttraction.GetLocation().y, ToAttraction.GetLocation().z);// /////////////////////////////
				}
			}
			p5.stroke(255, 0, 0);
			
		}finally {
			attracotrsConnectionlock.unlock();
		}
		
	}

	public class CheckPaths
	{
		
		List<Attraction> m_currentPath = new ArrayList<Attraction>();
		
		public List<ArrayList<Attraction>> m_allPossiblePaths = new  ArrayList< ArrayList<Attraction> > ();
		public Boolean CheckIfEntranceAndExitsConnected()
		{
			try
			{
				attracotrsConnectionlock.lock();
				m_allPossiblePaths.clear();
				int nCounter =0;
				for (Attraction value : p5.AttractionDictionary.values()) 
				{
					if(value.m_bIsEntrance)
					{
						GetFullPathToExit(value, nCounter);
						nCounter++;
					}
				}
				for (Attraction value : p5.AttractionDictionary.values()) 
				{
					value.m_visited = -1;
				}
			}finally {
				attracotrsConnectionlock.unlock();
			}
			
			
			return true;
		}
		
		void GetFullPathToExit(Attraction attarction, int currentVisitorCounter)
		{
			
			m_currentPath.add(attarction);
			if(attarction.m_bIsExit)
			{
				
				m_allPossiblePaths.add(new ArrayList<Attraction>( m_currentPath));
				for(int i =0; i< m_currentPath.size();++i)
				{
					ChangCeilingColor003.print( m_currentPath.get(i).GetId()+"<->");
				}
				ChangCeilingColor003.println(";");
			}
			
			
			if(attarction.m_visited != currentVisitorCounter )
			{
				attarction.m_visited = currentVisitorCounter;
				for(int i =0; i<attarction.m_ConnectedAttractors.size() ; ++i )
				{
					Attraction CurrentScanAttraction =(Attraction )attarction.m_ConnectedAttractors.get(i); 
					GetFullPathToExit(CurrentScanAttraction, currentVisitorCounter);
				}
			}
			m_currentPath.remove(m_currentPath.size() -1);
		}
	}
	
	

	void deployPerson(int pop, int type) {
		
		
		
		if( m_new.m_allPossiblePaths.size() > 0)
		{
			for (int i=0;i<pop;i++) {
				
				List<Attraction> selectedPath = m_new.m_allPossiblePaths.get((int)p5.random(0, m_new.m_allPossiblePaths.size()));
				
//				Vec3D oS=(Vec3D)p5.alisOrigin.get((int)p5.random(0, p5.alisOrigin.size()));//origin points are imported from Rhino/now is randomly in order/we need to define the order if we need--------------------------------------
//				Vec3D oStart=oS.copy();
//				Vec3D oEnd ;
//				do{
//					oEnd       =(Vec3D)p5.alisOrigin.get((int)p5.random(0, p5.alisOrigin.size()));//destination
//				}while((oEnd.x == oStart.x) || (oEnd.y == oStart.y));
//				
//				Destination destination = new Destination (p5,oEnd); 
//				destination.SetLoctation(oEnd);
				Person p=new Person(p5,selectedPath, type);
				p5.alisPeop.add(p);
			}
		}
		
	}


}
